import type { App } from "vue";

export const drag = (app: App) => {
    app.directive("drag", {
        mounted(el: HTMLElement, binding: any) {
            // 默认参数
            const defaultOpts = {
                dragDirection: 'n, e, s, w, ne, se, sw, nw, all',
                dragContainerId: '',
                dragBarClass: '',
                resizeEdge: 10,
                dirctDom: true,
                canDrag: true,
                canResize: true,
            };

            let isMove = false;
            binding.value = binding.value || {};
            // 合并默认配置和绑定值
            let cfg = Object.assign({}, defaultOpts, binding.value);

            // 从元素属性获取配置（所有属性带drag-前缀）
            const dragDirectionAttr = el.getAttribute('drag-direction');
            const dragContainerIdAttr = el.getAttribute('drag-container-id');
            const dragBarClassAttr = el.getAttribute('drag-bar-class');
            const resizeEdgeAttr = el.getAttribute('drag-resize-edge');
            const dirctDomAttr = el.getAttribute('drag-dirct-dom');
            const canDragAttr = el.getAttribute('drag-can-drag');
            const canResizeAttr = el.getAttribute('drag-can-resize');

            // 应用属性配置
            if (dragDirectionAttr) cfg.dragDirection = dragDirectionAttr;
            if (dragContainerIdAttr) cfg.dragContainerId = dragContainerIdAttr;
            if (dragBarClassAttr) cfg.dragBarClass = dragBarClassAttr;
            if (resizeEdgeAttr) cfg.resizeEdge = parseInt(resizeEdgeAttr, 10);
            if (dirctDomAttr !== null) cfg.dirctDom = dirctDomAttr === 'true';
            if (canDragAttr !== null) cfg.canDrag = canDragAttr === 'true';
            if (canResizeAttr !== null) cfg.canResize = canResizeAttr === 'true';

            // 存储元素原始transform（用于拖拽后恢复，null表示原本无transform）
            let originalTransform: string | null = null;
            // 存储最终的尺寸和位置数据
            let finalData: any = null;

            // 获取目标元素 resize方向
            function getDirection(e: MouseEvent) {
                const elTar = e.currentTarget as HTMLElement;
                let dir = '';
                const rect = elTar.getBoundingClientRect();
                const win = elTar.ownerDocument.defaultView;
                if (!win) return '';

                const offset = {
                    top: rect.top + win.pageYOffset,
                    left: rect.left + win.pageXOffset,
                    right: rect.right + win.pageXOffset,
                    bottom: rect.bottom + win.pageYOffset
                };

                if (e.pageY > offset.top && e.pageY < offset.top + cfg.resizeEdge) { dir += 'n'; }
                else if (e.pageY < offset.bottom && e.pageY > offset.bottom - cfg.resizeEdge) { dir += 's'; }

                if (e.pageX > offset.left && e.pageX < offset.left + cfg.resizeEdge) dir += 'w';
                else if (e.pageX < offset.right && e.pageX > offset.right - cfg.resizeEdge) dir += 'e';

                const directions = cfg.dragDirection.split(',').map((d: any) => d.trim());
                return directions.includes('all') || directions.includes(dir) ? dir : '';
            }

            // 设置约束范围
            function setConstraint(data: any) {
                if (cfg.dragContainerId) {
                    const constraintDom = document.querySelector(`#${cfg.dragContainerId}`);
                    if (!constraintDom) return;

                    const constraintRect = constraintDom.getBoundingClientRect();
                    if (data.left <= 0) data.left = 0;
                    if (data.top <= 0) data.top = 0;
                    if (data.top + data.height + data.borderTop + data.borderBottom >= constraintRect.height) {
                        data.top = constraintRect.height - data.height - data.borderTop - data.borderBottom;
                    }
                    if (data.left + data.width + data.borderLeft + data.borderRight > constraintRect.width) {
                        data.left = constraintRect.width - data.width - data.borderLeft - data.borderRight;
                    }
                }
            }

            // 恢复元素原始transform状态
            function restoreOriginalTransform() {
                if (originalTransform !== null) {
                    // 原有transform存在：恢复原始值（清除!important标记）
                    el.style.transform = originalTransform;
                    // 兼容部分浏览器对!important的缓存问题，二次赋值确保生效
                    if (el.style.transform === 'none !important') {
                        el.style.transform = originalTransform;
                    }
                } else {
                    // 原有transform不存在：彻底删除transform相关样式（兼容浏览器前缀）
                    el.style.removeProperty('transform');
                    el.style.removeProperty('-webkit-transform');
                    el.style.removeProperty('-moz-transform');
                    el.style.removeProperty('-ms-transform');
                    el.style.removeProperty('-o-transform');
                }
            }

            // 更新DOM样式
            function updateDom(data: any) {
                if (cfg.dirctDom) {
                    // 保存最终数据用于拖拽结束时强制应用
                    finalData = { ...data };
                    Object.assign(el.style, {
                        width: cfg.canResize ? `${data.width}px` : el.style.width,
                        height: cfg.canResize ? `${data.height}px` : el.style.height,
                        left: cfg.canDrag ? `${data.left}px` : el.style.left,
                        top: cfg.canDrag ? `${data.top}px` : el.style.top,
                        // 拖拽期间强制清除transform，确保位置计算准确
                        transform: 'none !important'
                    });
                }
            }

            // --------------------------
            // 核心修改1：新增事件派发逻辑
            // 拖拽/缩放结束后，派发尺寸变化事件
            // --------------------------
            function applyFinalStyles() {
                if (cfg.dirctDom && finalData) {
                    // 1. 先强制应用最终样式（原有逻辑）
                    el.style.width = cfg.canResize ? `${finalData.width}px` : el.style.width;
                    el.style.height = cfg.canResize ? `${finalData.height}px` : el.style.height;
                    el.style.left = cfg.canDrag ? `${finalData.left}px` : el.style.left;
                    el.style.top = cfg.canDrag ? `${finalData.top}px` : el.style.top;
                    // 2. 关键：从元素的 data-node 属性中获取节点ID（组件已存储节点ID在这里）
                    const dataNodeAttr = el.getAttribute('data-node');
                    const nodeId = dataNodeAttr ? JSON.parse(dataNodeAttr).id : '';

                    // 3. 派发自定义事件：携带节点ID和最新尺寸
                    if (nodeId && cfg.canResize) { // 只在尺寸变化时派发
                        el.dispatchEvent(new CustomEvent('drag-size-change', {
                            bubbles: false, // 不冒泡，避免干扰其他元素
                            detail: {
                                nodeId: nodeId,       // 节点唯一ID（用于组件定位存储）
                                width: finalData.width,  // 最新宽度
                                height: finalData.height // 最新高度
                            }
                        }));
                    }
                }
            }

            // 鼠标移动/离开（不变）
            el.onmousemove = function (e: MouseEvent) {
                if (cfg.dragBarClass && e.target instanceof Element && e.target.classList.contains(cfg.dragBarClass) && cfg.canDrag) {
                    el.style.cursor = 'move';
                    return;
                }
                const dir = getDirection(e);
                el.style.cursor = dir ? `${dir}-resize` : '';
            };

            el.onmouseleave = function () {
                el.style.cursor = '';
            };

            // 鼠标按下事件处理
            el.onmousedown = function (e: MouseEvent) {
                isMove = false;
                finalData = null; // 重置最终数据

                // 检查是否点击了拖拽
                if (cfg.dragBarClass && e.target instanceof Element && e.target.classList.contains(cfg.dragBarClass)) {
                    isMove = true;
                    document.body.style.cursor = 'move';
                }

                const style = window.getComputedStyle(el);
                const getStyleNumValue = (key: string) => parseInt(style.getPropertyValue(key), 10) || 0;

                const rect = el.getBoundingClientRect();
                const data = {
                    width: getStyleNumValue("width"),
                    height: getStyleNumValue("height"),
                    left: getStyleNumValue("left"),
                    top: getStyleNumValue("top"),
                    borderLeft: getStyleNumValue("border-left-width"),
                    borderTop: getStyleNumValue("border-top-width"),
                    borderRight: getStyleNumValue("border-right-width"),
                    borderBottom: getStyleNumValue("border-bottom-width"),
                    deltX: e.pageX - rect.left,
                    deltY: e.pageY - rect.top,
                    startX: rect.left,
                    startY: rect.top
                };

                const dir = getDirection(e);
                if (!dir && !isMove) return;

                // 记录原始transform并临时清除
                originalTransform = el.style.transform || null;
                el.style.transform = 'none !important';

                // 创建遮罩防止事件穿透
                const mask = document.createElement("div");
                mask.style.cssText = "position:absolute;top:0;bottom:0;left:0;right:0;z-index:9999;";
                document.body.appendChild(mask);

                // 鼠标移动处理函数
                const handleMouseMove = (edom: MouseEvent) => {
                    const resizeActions = {
                        e() {
                            data.width = edom.pageX - data.startX + data.borderLeft + data.borderRight;
                        },
                        s() { data.height = edom.pageY - data.startY + data.borderBottom + data.borderTop; },
                        n() {
                            const deltheight = data.startY + data.borderBottom + data.borderTop - edom.pageY;
                            data.height += deltheight;
                            data.top -= deltheight;
                            data.startY -= deltheight;
                        },
                        w() {
                            const deltwidth = data.startX + data.borderLeft + data.borderRight - edom.pageX;
                            data.width += deltwidth;
                            data.left -= deltwidth;
                            data.startX -= deltwidth;
                        }
                    };
                    // 执行对应方向的调整
                    if (dir && cfg.canResize) {
                        Object.keys(resizeActions).forEach(key => {
                            if (dir.includes(key)) {
                                resizeActions[key as keyof typeof resizeActions]();
                            }
                        });
                    }

                    // 拖拽处理
                    if (isMove && cfg.canDrag) {
                        const deltX = edom.pageX - data.startX - data.deltX;
                        const deltY = edom.pageY - data.startY - data.deltY;
                        const newLeft = getStyleNumValue("left") + deltX;
                        const newTop = getStyleNumValue("top") + deltY;

                        data.left = newLeft;
                        data.top = newTop;
                        data.startX += deltX;
                        data.startY += deltY;
                        setConstraint(data);
                    }

                    // 更新DOM
                    updateDom(data);

                    // 触发自定义事件
                    el.dispatchEvent(new CustomEvent('bindUpdate', { detail: { ...data } }));
                };

                // 鼠标释放处理函数
                const handleMouseUp = () => {
                    document.body.style.cursor = '';
                    document.removeEventListener('mousemove', handleMouseMove);
                    document.removeEventListener('mouseup', handleMouseUp);
                    isMove = false;

                    applyFinalStyles(); // 这里会触发尺寸事件派发

                    // 恢复原始transform
                    restoreOriginalTransform();
                    originalTransform = null;

                    // 移除遮罩
                    if (mask.parentNode) document.body.removeChild(mask);
                };

                // 绑定全局事件
                document.addEventListener('mousemove', handleMouseMove);
                document.addEventListener('mouseup', handleMouseUp);

                // 设置鼠标样式
                if (dir) { 
                    document.body.style.cursor = `${dir}-resize`;
                }
                // 阻止默认行为防止文本选中
                e.preventDefault();
            };
        },
        // 指令解绑时清理事件和样式
        unmounted(el: HTMLElement) {
            el.onmousemove = null;
            el.onmouseleave = null;
            el.onmousedown = null;
            el.style.removeProperty('transform');
        }
    });
};